
/****************************************************************************/
/*Copyright (c) 2011, Florent DEVILLE.                                      */
/*All rights reserved.                                                      */
/*                                                                          */
/*Redistribution and use in source and binary forms, with or without        */
/*modification, are permitted provided that the following conditions        */
/*are met:                                                                  */
/*                                                                          */
/* - Redistributions of source code must retain the above copyright         */
/*notice, this list of conditions and the following disclaimer.             */
/* - Redistributions in binary form must reproduce the above                */
/*copyright notice, this list of conditions and the following               */
/*disclaimer in the documentation and/or other materials provided           */
/*with the distribution.                                                    */
/* - The names of its contributors cannot be used to endorse or promote     */
/*products derived from this software without specific prior written        */
/*permission.                                                               */
/* - The source code cannot be used for commercial purposes without         */ 
/*its contributors' permission.                                             */
/*                                                                          */
/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       */
/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         */
/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS         */
/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE            */
/*COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,       */
/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;          */
/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER          */
/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT        */
/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN         */
/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           */
/*POSSIBILITY OF SUCH DAMAGE.                                               */
/****************************************************************************/

#include "RTPrimPlan.h"

namespace RT
{
	/*Constructor*/
	RTPrimPlan ::RTPrimPlan(const RTPoint3f& p1, const RTPoint3f& p2, const RTPoint3f& p3):RTIPrimitive()
	{
		m_p1=p1; m_p2=p2; m_p3=p3;

		RTVector3f v1 = p2 - p1;
		RTVector3f v2 = p3 - p1;
		m_normal = v1.cross(v2);
		m_normal.normalize();

		m_A = m_normal.x;
		m_B = m_normal.y;
		m_C = m_normal.z;
	
		m_D = -m_A * p1.x - m_B * p1.y - m_C * p1.z;

		m_point = p1;
	}

	/*Destructor*/
	RTPrimPlan::~RTPrimPlan(){}

	/*Calculate intersection between a ray and the plan*/
	bool RTPrimPlan::intersect(const RTRay& ray, F32& dist, bool useGlobalCoordinates)
	{
		//change the coordinate system
		RTRay r;
		if (useGlobalCoordinates)
			globalToLocal(ray, r);
		else
			convertRayToLocalCoordinates(ray, r);

		F32 denom = m_normal.dot(r.getDirection());

		RTVector3f temp = r.getOrigin() - m_point;
		//temp.normalize();
		F32 num = m_normal.dot(temp);

		if(denom == 0)
			return false;

		F32 t = -num/denom;

		if(t<=0.1f)
			return false;

		dist = t;
		return true;
	}

	/*Calculate the normal*/
	void RTPrimPlan::computeNormal(const RTRay& ray, F32 /*dist*/, RTVector3f& normal)const
	{
		//store the local normal
		normal.x = m_A;
		normal.y = m_B;
		normal.z = m_C;

		//reset to the global coordinate systeme
		convertNormalToGlobalCoordinates(normal, normal);

		//get the opposite normal if needed
		F32 dot = normal.dot(ray.getDirection());
		if (dot > 0)
			normal *= -1;

	}

	/*Check if the point is a point of the plan*/
	bool RTPrimPlan::isInside(const RTVector3f& p)const
	{
		//convert p to local coordinates
		RTVector3f localP;
		convertPointToLocalCoordinates(p, localP);

		//check distance between the poI32 and the plan. If 0 return true
		//equation d(A,P) = (ax * Pa + ay * Pb + az * Pc + Pd) / (||n||)
		F64 num = m_normal.dot(localP) + m_D;
		F64 denum = m_normal.norme();

		F64 dist = num / denum;
		if(dist == 0)
			return true;

		return false;
	}

}